package com.lagou.service.impl;

import com.lagou.dao.AuthCodeDao;
import com.lagou.model.AuthCode;
import com.lagou.service.AuthCodeService;
import com.lagou.service.EmailService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * 验证码服务
 */
@Service
public class AuthCodeServiceImpl implements AuthCodeService {
    /**
     * 验证码的最大值
     */
    private static final int MAX_CODE = 10000;

    /**
     * 验证码有效时间，以毫秒为单位
     */
    private static final int CODE_EXPIRE_TIME = 600000;

    /**
     * 验证码DAO
     */
    @Autowired
    private AuthCodeDao authCodeDao;

    /**
     * 邮件服务
     */
    @Reference
    private EmailService emailService;

    /**
     * 随机数生成器
     */
    private Random random = new Random();

    /**
     * 发送验证码到指定的邮箱
     *
     * @param email 指定的邮箱
     * @return 操作结果
     */
    @Override
    public boolean sendCode(String email) {
        // 生成验证码
        String code = Integer.toString(random.nextInt(MAX_CODE));

        try {
            // 保存到数据库
            saveCode(email, code);

            // 发送验证码
            return emailService.sendEmail(email, code);
        } catch (Exception ex) {
            System.out.println(String.format("Failed to send code to %s", email));
            ex.printStackTrace();
        }

        return false;
    }

    /**
     * 校验验证码
     *
     * @param email 验证码对应的邮箱
     * @param code 验证码
     * @return 校验结果
     */
    @Override
    public int validateCode(String email, String code) {
        // 搜索验证码记录
        AuthCode authCode = new AuthCode();
        authCode.setEmail(email);
        authCode.setCode(code);

        Example<AuthCode> example = Example.of(authCode);
        Sort sort = Sort.by(Sort.Order.desc("createTime"));

        List<AuthCode> authCodes = Collections.emptyList();
        try {
            authCodes = authCodeDao.findAll(example, sort);
            if (authCodes.isEmpty()) {
                return 1;
            }
        } catch (Exception ex) {
            System.out.println(String.format("Failed to query given code %s", code));
            ex.printStackTrace();
        }

        // 判断是否过期
        AuthCode matchedCode = authCodes.get(0);
        Date expireTime = matchedCode.getExpireTime();

        long now = System.currentTimeMillis();
        if (now > expireTime.getTime()) {
            return 2;
        }

        return 0;
    }

    /**
     * 保存验证码
     *
     * @param email 验证码对应的邮箱
     * @param code 验证码
     */
    private void saveCode(String email, String code) {
        AuthCode authCode = new AuthCode();
        authCode.setCode(code);
        authCode.setEmail(email);

        Date createTime = new Date();
        authCode.setCreateTime(createTime);

        Date expireTime = new Date(createTime.getTime() + CODE_EXPIRE_TIME);
        authCode.setExpireTime(expireTime);

        authCodeDao.save(authCode);
    }
}
